import axios from 'axios'
// 1. 导入 vuex 对应的 store 模块
import store from '@/store/index'
// 导入路由模块，得到路由实例对象
import router from '@/router/index'

// 导入大数处理的包
import bigInt from 'json-bigint'

// data 是服务器响应回来的，待处理的数据
const transBigInt = data => {
  // 如果服务器接口调用成功后，没有任何响应体，则 data 为空
  // 此时，对于没有请求体的清空，要进行非法值得判断，防止后续转化失败！
  if (!data) return ''
  try {
    // 尝试进行大数处理
    // 优选方案
    return bigInt.parse(data)
  } catch {
    // 大数处理失败，单纯的进行 JSON -> 对象的转换
    // 兜底的方案
    return JSON.parse(data)
  }
}

// 创建 axios 的实例对象
const instance = axios.create({
  // 配置请求的根路径
  baseURL: 'http://toutiao-app.itheima.net',
  // 对服务器响应回来的数据，进行预处理
  transformResponse: [transBigInt]
})

// TODO：要为 instance 实例，添加请求和响应拦截器
// 添加请求拦截器
instance.interceptors.request.use(
  function(config) {
    // 2. 从 vuex 中获取到 Token 相关的数据对象，注意：tokenInfo 有可能是一个空对象
    const tokenInfo = store.state.tokenInfo
    // 3. 只有当 tokenInfo.token 有值的时候，才添加 Authorization 身份认证字段
    if (tokenInfo.token) {
      // 4. 为请求头添加 Authorization 身份认证的字段
      config.headers.Authorization = 'Bearer ' + tokenInfo.token
    }
    // console.log('触发了请求拦截器', config)
    // 在发送请求之前做些什么
    return config
  },
  function(error) {
    // 对请求错误做些什么
    return Promise.reject(error)
  }
)

// 添加响应拦截器
// instance.interceptors.response.use(
//   function(response) {
//     // console.log('触发了响应拦截器', response)
//     // 对响应数据做点什么
//     return response
//   },
//   function(error) {
//     // 对响应错误做点什么
//     // 拿到失败之后服务器响应的结果，并判断状态码是否为 401【401 表示 Token 失效】
//     if (error.response && error.response.status === 401) {
//       // 证明 Token 过期了，
//       // 1. 清除 Vuex 中的数据
//       store.commit('cleanState')
//       // 2. 强制用户跳转到登录页面
//       router.push('/login?pre=' + router.currentRoute.fullPath)
//     }
//     return Promise.reject(error)
//   }
// )

// 响应拦截器
instance.interceptors.response.use(
  function(response) {
    // console.log('触发了响应拦截器', response)
    // 对响应数据做点什么
    return response
  },
  async function(error) {
    // 请求失败之后，调用响应拦截器的失败回调函数
    const tokenInfo = store.state.tokenInfo
    if (error.response && error.response.status === 401 && tokenInfo.token) {
      // Token 过期了，需要进行无感知的刷新
      try {
        // 3.1 TODO: 发起请求，根据 refresh_token 重新请求一个有效的新 token
        const { data: res } = await axios({
          method: 'PUT',
          url: 'http://toutiao-app.itheima.net/v1_0/authorizations',
          headers: {
            Authorization: 'Bearer ' + tokenInfo.refresh_token
          }
        })
        // 3.2 TODO: 更新 Store 中的 Token
        store.commit('updateTokenInfo', {
          refresh_token: tokenInfo.refresh_token,
          token: res.data.token
        })
        // 3.3 基于上次未完成的配置，重新发起请求
        return instance(error.config)
      } catch {
        // 先清空 Store 和本地的数据
        store.commit('cleanState')
        // 再强制跳转到登录页
        router.push('/login?pre=' + router.currentRoute.fullPath)
      }
    }
    return Promise.reject(error)
  }
)

// 向外共享 axios 实例对象
export default instance
